package c7;

import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class WordsCounter {
    private final int counter;
    private final boolean lastSpace;

    public WordsCounter(int counter, boolean lastSpace) {
        this.counter = counter;
        this.lastSpace = lastSpace;
    }
    public WordsCounter accumulate(Character c){
      if(Character.isWhitespace(c)){
          return lastSpace?
                  this:
                  new WordsCounter(counter,true);
      }else {
          return lastSpace?
                  new WordsCounter(counter+1,false):
                  this;
      }
    }

    public WordsCounter combine(WordsCounter wordsCounter){
        return new WordsCounter(counter+wordsCounter.counter,wordsCounter.lastSpace);
    }

    public int getCounter() {
        return counter;
    }

    public static void main(String[] args){
        final String SENTENCE =
                " Nel mezzo del cammin di nostra vita " +
                        "mi ritrovai in una selva oscura" +
                        " ché la dritta via era smarrita ";
        System.out.println("Found " + countWordsIteratively(SENTENCE) + " words");

        Stream<Character> stream=IntStream.range(0,SENTENCE.length())
                .mapToObj(SENTENCE::charAt);
        System.out.println("Found Stream " + countWordsStream(stream) + " words");

        //System.out.println("Found Parallel Stream" + countWordsStream(stream.parallel()) + " words");

        Spliterator<Character> spliterator = new WordCounterSpliterator(SENTENCE);
        Stream<Character> streamSpliterator = StreamSupport.stream(spliterator, true);
        System.out.println("Found streamSpliterator " + countWordsStream(streamSpliterator) + " words");

    }

    public static int countWordsIteratively(String s){
        int counter=0;
        boolean lastSpace=true;
        for(char c:s.toCharArray()){
            if(Character.isWhitespace(c)){
                lastSpace=true;
            }else{
                if(lastSpace) counter++;
                lastSpace=false;
            }
        }
        return counter;
    }

    public static int countWordsStream(Stream<Character> stream){
        WordsCounter wordsCounter=stream.reduce(new WordsCounter(0,true),
                WordsCounter::accumulate,
                WordsCounter::combine);
        return wordsCounter.getCounter();
    }

    private static class WordCounterSpliterator implements Spliterator<Character> {

        private final String string;
        private int currentChar = 0;

        private WordCounterSpliterator(String string) {
            this.string = string;
        }

        //处理当前字符，如果还有字符就返回true
        @Override
        public boolean tryAdvance(Consumer<? super Character> action) {
            action.accept(string.charAt(currentChar++));
            return currentChar < string.length();
        }

        //定义拆分逻辑
        @Override
        public Spliterator<Character> trySplit() {
            int currentSize = string.length() - currentChar;
            //下限10个，小于10的顺序执行
            if (currentSize < 10) {
                return null;
            }
            for (int splitPos = currentSize / 2 + currentChar; splitPos < string.length(); splitPos++) {
                if (Character.isWhitespace(string.charAt(splitPos))) {
                    Spliterator<Character> spliterator = new WordCounterSpliterator(string.substring(currentChar, splitPos));
                    currentChar = splitPos;
                    return spliterator;
                }
            }
            return null;
        }

        //还需要遍历的元素长度
        @Override
        public long estimateSize() {
            return string.length() - currentChar;
        }

        @Override
        public int characteristics() {
            return ORDERED + SIZED + SUBSIZED + NONNULL + IMMUTABLE;
        }
    }
}
